package com.blue.http.invoke;

import com.alibaba.fastjson.JSONException;
import com.blue.core.util.JsonUtil;
import com.blue.http.annotation.HttpFilterParser;
import com.blue.http.annotation.HttpParser;
import com.blue.http.annotation.HttpUrlMethod;
import com.blue.http.config.ErrorConfig;
import com.blue.http.filter.Filter;
import com.blue.http.message.*;
import com.blue.http.util.HttpException;
import com.blue.http.util.HttpLogUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;

import javax.validation.ValidationException;
import java.util.List;

/**
 * HTTP调用
 * 
 * @author zhengj
 * @since 1.0 2017年3月14日
 */
public class Invoker
{
	private static Logger logger = LoggerFactory.getLogger(Invoker.class);
	
	private final HttpParser httpParser;
	private final HttpFilterParser httpFilterParser;
	private ErrorConfig errorConfig = ErrorConfig.getInstance();
	
	public Invoker(HttpParser httpParser, HttpFilterParser httpFilterParser)
	{
		this.httpParser = httpParser;
		this.httpFilterParser = httpFilterParser;
	}
	
	/**
	 * 方法调用
	 * 
	 * @param request 参数
	 */
	public HttpResponse invoke(HttpRequest request)
	{
		HttpResponse response = new DefaultHttpResponse();
		Exception exp = null;

		try
		{
			boolean result = this.preHandler(request, response);
			if (!result)
				return response;

			this.handler(request, response);

		}
		catch (ValidationException e)
		{
			exp = e;
			response.setCode(ErrorConfig.PARAM);
			response.setMsg(errorConfig.get(ErrorConfig.PARAM));
			response.setExtmsg(e.getMessage());
			HttpLogUtil.log(request, response, e);
		}
		catch (BeansException e)
		{
			exp = e;
			response.setCode(ErrorConfig.NOT_FOUND);
			response.setMsg(errorConfig.get(ErrorConfig.NOT_FOUND));
			HttpLogUtil.log(request, response, e);
		}
		catch (JSONException e)
		{
			exp = e;
			response.setCode(ErrorConfig.JSON);
			response.setMsg(errorConfig.get(ErrorConfig.JSON));
			HttpLogUtil.log(request, response, e);
		}
		catch (HttpException e)
		{
			exp = e;
			response.setCode(e.getCode());
			response.setMsg(e.getMessage());
			response.setExtmsg(e.getExtMessage());
			HttpLogUtil.log(request, response, e);
		}
		catch (Exception e)
		{
			exp = e;
			response.setCode(ErrorConfig.ERROR);
			response.setMsg(errorConfig.get(ErrorConfig.ERROR));
			HttpLogUtil.log(request, response, e);
		}
		catch (Throwable e)
		{
			logger.error("发生严重错误：", e);
		}
		finally
		{
			this.afterHandler(request, response, exp);
		}
		
		return response;
	}

	private void handler(HttpRequest request, HttpResponse response) throws Throwable
	{
		HttpUrlMethod method = httpParser.getUrlMethod(request.getUrl(), request.getHttpMethod());
		if (method != null)
		{
			response.setContentType(method.getContentType());
		}
		Object obj = httpParser.invoke(request, method);
		if (obj != null)
		{
			if (obj instanceof CharSequence)
			{
				response.setResult(obj.toString());
			}
			else if (obj instanceof View)
			{
				View v = (View)obj;
				response.setView(v);
			}
			else if (obj instanceof Download)
			{
				Download d = (Download)obj;
				response.setDownload(d);
			}
			else
			{
				response.setResult(JsonUtil.output(obj));
			}
		}
		if (!response.isView() && response.getDownload() == null)
		{
			HttpLogUtil.log(request, response.getResult());
		}
	}

	private boolean preHandler(HttpRequest request, HttpResponse response) throws Exception
	{
		List<Filter> filterList = httpFilterParser.allFilter();
		if (filterList == null || filterList.isEmpty())
			return true;
		
		String url = request.getUrl();
		for (Filter filter : filterList)
		{
			if (!httpFilterParser.match(filter.getClass(), url))
				continue;

			boolean result = filter.preHandle(request, response);
			if (!result)
				return false;
		}
		return true;
	}
	
	private void afterHandler(HttpRequest request, HttpResponse response, Exception e)
	{
		List<Filter> filterList = httpFilterParser.allFilter();
		if (filterList == null || filterList.isEmpty())
			return;

		String url = request.getUrl();
		for (int i = filterList.size() - 1; i >= 0; i--)
		{
			Filter filter = filterList.get(i);
			if (!httpFilterParser.match(filter.getClass(), url))
				continue;

			try
			{
				filter.afterHandle(request, response, e);
			}
			catch (Exception ex)
			{
				logger.error("调用链发生异常：", ex);
			}
		}
	}
	
	
}
